/* ---------------------------------------------------------------------------
 ** This software is in the public domain, furnished "as is", without technical
 ** support, and with no warranty, express or implied, as to its usefulness for
 ** any purpose.
 **
 ** -------------------------------------------------------------------------*/

import { MediaStream } from './mediastream.js'

const scriptPath = new URL(import.meta.url).pathname

class VideoWsElement extends HTMLElement {
  static observedAttributes = ['url']

  constructor() {
    super()
    this.shadowDOM = this.attachShadow({ mode: 'open' })
    this.shadowDOM.innerHTML = `
                  <link rel="stylesheet" href="${scriptPath.substring(0, scriptPath.lastIndexOf('/'))}/video-ws.css">
                  <div class="videoContent">
                    <video id="video" muted="false" playsinline preload="none"></video>
                    <div id="spinner" class="loading">
                        <div class="w-full h-full" >
                            <svg
                                xmlns="http://www.w3.org/2000/svg"
                                class="icon-loader animate-spin w-full h-full"
                                width="24px"
                                height="24px"
                                viewBox="0 0 24 24"
                                stroke-width="2"
                                stroke="currentColor"
                                fill="none"
                                stroke-linecap="round"
                                stroke-linejoin="round"
                                >
                                <path stroke="none" d="M0 0h24v24H0z" fill="none" />
                                <path d="M12 6l0 -3" />
                                <path d="M16.25 7.75l2.15 -2.15" />
                                <path d="M18 12l3 0" />
                                <path d="M16.25 16.25l2.15 2.15" />
                                <path d="M12 18l0 3" />
                                <path d="M7.75 16.25l-2.15 2.15" />
                                <path d="M6 12l-3 0" />
                                <path d="M7.75 7.75l-2.15 -2.15" />
                            </svg>
                        </div>
                    </div>
                  </div>`

    this.audioContext = new AudioContext()
    const canvas = document.createElement('canvas')
    this.stream = canvas.captureStream()
    const audioTrack = this.audioContext.createMediaStreamDestination().stream.getAudioTracks()[0]
    this.mediaStream = new MediaStream(
      canvas,
      this.audioContext,
      (loaded) => {
        if (loaded) {
          this.shadowDOM.getElementById('spinner').classList.remove('loading')
          this.shadowDOM.getElementById('spinner').style.display = 'none'
        } else {
          this.shadowDOM.getElementById('spinner').classList.add('loading')
          this.shadowDOM.getElementById('spinner').style.display = 'block'
        }
      },
      (loaded) => {
        if (loaded) {
          this.stream.addTrack(audioTrack)
          this.audioContext.resume()
        } else {
          this.stream.removeTrack(audioTrack)
          this.audioContext.suspend()
        }
      }
    )
  }

  connectedCallback() {
    console.log('connectedCallback')

    const video = this.shadowDOM.getElementById('video')
    video.srcObject = this.stream
    video.addEventListener('play', () => this.audioContext.resume())
    video.addEventListener('pause', () => this.audioContext.suspend())
    video.addEventListener('volumechange', () => this.mediaStream.setVolume(video.muted ? 0 : video.volume))
    this.audioContext.onstatechange = () => {
      switch (this.audioContext.state) {
        case 'suspended':
          video.muted = true
          break
        case 'running':
          video.muted = false
          break
      }
    }
    video.play()
  }

  disconnectedCallback() {
    console.log('disconnectedCallback')
    this.mediaStream.close()
  }

  attributeChangedCallback(name, oldValue, newValue) {
    console.log(`Attribute ${name} has changed.`)
    if (name === 'url' && oldValue !== newValue) {
      this.shadowDOM.getElementById('spinner').classList.add('loading')
      this.mediaStream.connect(newValue)
    }
  }
}

customElements.define('video-ws', VideoWsElement)
